package com.java.study.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.java.study.common.utils.JwtUtil;
import com.java.study.common.utils.R;
import com.java.study.common.utils.WXPayUtil;
import com.java.study.config.WechatConfig;
import com.java.study.entity.UserEntity;
import com.java.study.entity.VideoOrderEntity;
import com.java.study.service.UserService;
import com.java.study.service.VideoOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

/**
 * 文档https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
 */

@Controller
@RequestMapping("/api/v1/wechat")
public class WechatController {

    @Autowired
    private WechatConfig wechatConfig;
    @Autowired
    private UserService userService;
    @Autowired
    private VideoOrderService videoOrderService;

    /**
     * 生成微信扫码登录二维码url
     */
    @GetMapping("login_url")
    @ResponseBody
    public R loginUrl(@RequestParam(value = "access_page",required = true)String accessPage) throws UnsupportedEncodingException {
        String redirectUrl = URLEncoder.encode(wechatConfig.getOpenRedirectUrl(),"GBK"); //获取开放平台重定向地址,GBK编码
        String qrcodeUrl = String.format(WechatConfig.OPEN_QRCODE_URL,wechatConfig.getOpenAppid(),redirectUrl,accessPage);
        return R.ok(qrcodeUrl);
    }

    /**
     * 微信扫码登录,回调地址
     * 用户扫码后,微信通过redirectUrl调用我们的接口,并在url上拼接?code=CODE
     * 拿到code后,通过code换取access_token和openid,再通过access_token和openid获取用户信息
     */
    @GetMapping("/user/callback")
    public void wechatUserCallback(@RequestParam(value = "code") String code,
                                   String state, HttpServletResponse response) throws Exception {
        UserEntity user = userService.saveWeChatUser(code);
        if (user != null) {
            //生成jwt token
            String token = JwtUtil.createJWT(String.valueOf(user.getId()),user.getName(),user.getHeadImg());
            // state 当前用户的页面地址，需要拼接 http://  这样才不会站内跳转
            response.sendRedirect(state+"?token="+token+"&head_img="+user.getHeadImg()+"&name="+URLEncoder.encode(user.getName(),"UTF-8"));
        }
    }

    /**
     * 微信扫码支付回调(微信回调是以流的形式)
     */
    @RequestMapping("/order/callback")
    public void orderCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ServletInputStream inputStream = request.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        inputStream.close();
        Map<String, String> callbackMap = WXPayUtil.xmlToMap(sb.toString());

        //判断签名是否正确
        if (WXPayUtil.isCorrectSign(WXPayUtil.mapToSortMap(callbackMap), wechatConfig.getKey())) {
            if ("SUCCESS".equals(callbackMap.get("result_code"))) {
                String outTradeNo = callbackMap.get("out_trade_no");
                VideoOrderEntity videoOrder = videoOrderService.getOne(new LambdaQueryWrapper<VideoOrderEntity>().eq(VideoOrderEntity::getOutTradeNo, outTradeNo));
                //状态是未支付且金额相同
                if (videoOrder!= null && videoOrder.getState() == 0 && videoOrder.getTotalFee() .equals(Integer.valueOf(callbackMap.get("total_fee")))) {
                //更新数据库
                    videoOrder.setState(1);
                    videoOrder.setOpenid(callbackMap.get("openid"));
                    videoOrder.setNotifyTime(new Date());
                    boolean update = videoOrderService.updateById(videoOrder);
                    if (update) {
                        //通知微信订单处理完成
                        response.setContentType("text/xml");
                        response.getWriter().println("SUCCESS");
                        return;
                    }
                }
            }
        }

        response.setContentType("text/xml");
        response.getWriter().println("FAIL");

    }


}
